package com.adf.gencode;

import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.setting.Setting;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.*;

public class CodeGen {

    //用于启动代码生成
    public  static void  main(String[] args){

        // do1 方法1

        // do 2 方法
        do2();
    }

    private static void  do2(){
        Setting setting = new Setting("gencodeDo2.setting");
        initGlobalConfig(setting);

        // 当前项目的根目录
        String projectRootDir = setting.getStr("targetProject",System.getProperty("user.dir"));

        System.out.println(projectRootDir);
        String dbUrl = setting.get("db.url");
        String dbUsername = setting.get("db.username");
        String dbPassword = setting.get("db.password");

        String author = setting.get("author");

        //父目录名称
        String parentPackage="com.adf";

        String packageModulePath = setting.getStr("packageModulePath");
        String packageModuleName = setting.getStr("packageModuleName");
        System.out.println("packageModuleName:".concat(packageModuleName));

        String voQueryXmlPath = projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("voQueryXmlPath")).render(setting);

        //生成的表名列表
        String genTableNames = "sys_user,sys_role,sys_userrole";

        FastAutoGenerator fastAutoGenerator =FastAutoGenerator.create(dbUrl,dbUsername,dbPassword);
        // 全局配置
        fastAutoGenerator.globalConfig(builder -> {

            builder.author(author);
            //builder.enableSwagger();
            // 生成后无须打开资源管理器
            builder.disableOpenDir();
            builder.outputDir(projectRootDir);
            builder.commentDate("yyyy-MM-dd HH:mm:ss");
        });

        fastAutoGenerator.packageConfig(builder -> {

            builder.parent(parentPackage);
            // 当前要生成的模块名称
            builder.moduleName("admin");

            // 定义各自生成的文件
            Map<OutputFile,String> pathInfo = new HashMap<>();
            // 实体类输出
            // TemplateUtil.createEngine().getTemplate(setting.get("entityOutPath")).render(setting) 这句话是使用模板字符进行字符串输出替换

            //绝对路径
            String entityOutPath = projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("entityOutPath")).render(setting);
            System.out.println("entiy path:".concat(entityOutPath));
            pathInfo.put(OutputFile.entity, entityOutPath);
            pathInfo.put(OutputFile.mapper, projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("mapperOutPath")).render(setting));
            pathInfo.put(OutputFile.xml, projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("mapperXmlOutPath")).render(setting));
            pathInfo.put(OutputFile.service, projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("serviceOutPath")).render(setting));
            pathInfo.put(OutputFile.serviceImpl, projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("serviceImplOutPath")).render(setting));
            pathInfo.put(OutputFile.controller, projectRootDir+"/"+ TemplateUtil.createEngine().getTemplate(setting.get("controllerOutPath")).render(setting));
            //pathInfo.put(OutputFile.,projectRootDir+"/");
            builder.parent(setting.get("packageParent")) // 设置父包名
                    .xml("mapper.mapping")
                    //.other("dto") // 设置dto包名
                    .moduleName(setting.get("moduleName"))
                    .pathInfo(pathInfo);

        });


        // 配置策略
        fastAutoGenerator.strategyConfig(builder -> {

            // 对哪些表要生成
            builder.addInclude(genTableNames);
            builder.addTablePrefix("sys_");
            // 对实体的生成控制
            builder.entityBuilder().enableLombok().enableFileOverride();

            //对控制器的控制 可以设置为可以覆盖 如果不想生成
            //builder.controllerBuilder().disable();
            builder.controllerBuilder().enableRestStyle();

            //builder.controllerBuilder().enableRestStyle()

            // mapper 的配置
            builder.mapperBuilder().enableBaseResultMap().enableFileOverride();

            //
            builder.serviceBuilder();

            // service 配置

        });

        // 设置哪些参数可以传到模板中
        fastAutoGenerator.injectionConfig(builder -> {
            Map<String,Object> tmpMap = new HashMap<>();

            // 另入其他参数
            tmpMap.put("Test","TestTest");

            //根据路径来替换模板的package名称

            String parentPackagePath = packageModulePath.replace("/",".");
            tmpMap.put("parentPackagePath",parentPackagePath);
            tmpMap.put("packageModuleName",packageModuleName);
            tmpMap.put("voQueryXmlPath",voQueryXmlPath);

            tmpMap.put("setting",setting);
            // 向模板注入自定义参数
            builder.customMap(tmpMap);

            // 自定义生成文件
            //

            Map<String,String> customFiles = new HashMap<>();
            customFiles.put("List","/templates/vue.List.ftl");
            customFiles.put("View","/templates/vue.View.ftl");
            customFiles.put("Add","/templates/vue.Add.ftl");
            customFiles.put("Api","/templates/vue.Api.ftl");
            customFiles.put("VoQuery", "/templates/vo.query.java.ftl");
            customFiles.put("VoQueryMapperXml","/templates/vo.querymapper.xml.ftl");
            customFiles.put("VoQueryMapper","/templates/vo.querymapper.java.ftl");

            customFiles.put("VoQueryServiceInterface","/templates/vo.query.service.interface.java.ftl");
            customFiles.put("VoQueryServiceImpl","/templates/vo.query.service.impl.java.ftl");

            builder.customFile(customFiles);




        });

        // 配置模板引擎
        // 获取Freemarker配置



        fastAutoGenerator.templateEngine(new AdfFreemarkerTemplateEngine(){

        });


        // 执行代码生成

        fastAutoGenerator.execute();
    }

    private static void  do1(){

    }

    //初始化全局变化，通过Setting来进行
    private static void  initGlobalConfig(Setting setting){

        String projectRootDir = setting.getStr("targetProject",System.getProperty("user.dir"));
        String resourcesPath = projectRootDir + "/"+TemplateUtil.createEngine().getTemplate(setting.get("resourcesPath")).render(setting);
        String genConfigPath = resourcesPath + "/genConfig.xml";

        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(new File(genConfigPath));

            // 读取所有的tableList下所有的tableInfo

            Element rootElem = document.getRootElement();
            Element tableListElem = rootElem.element("tableList");
            List<Element> elemTableList = tableListElem.elements("table");
            for(Element element : elemTableList){

                String tableId =  element.attributeValue("id");
                String entityName = element.attributeValue("entityName");
                String desc = element.attributeValue("desc");
                // 查询当前的id的表是否已经存储
                Optional<AdfTable> tmpTable = GlobalConfig.globalTableList.findFirst(x->{
                    return x.getTableName().equals(tableId);
                });

                if(tmpTable.isEmpty())
                {
                    AdfTable adfTable = new AdfTable();
                    adfTable.setTableName(tableId);
                    adfTable.setEntityName(entityName);
                    adfTable.setDesc(desc);
                    GlobalConfig.globalTableList.add(adfTable);
                }

            }

            // 读取所有的query
            List<Element> elemQueryList = rootElem.elements("select");
            for(Element element : elemQueryList){

                String queryId =  element.attributeValue("id");
                String entityName = element.attributeValue("entityName");
                String sql = element.getText();
                // 查询当前的id的表是否已经存储
                Optional<AdfTable> tmpTable = GlobalConfig.globalQueryList.findFirst(x->{
                    return x.getTableName().equals(queryId);
                });

                if(tmpTable.isEmpty())
                {
                    AdfTable adfTable = new AdfTable();
                    adfTable.setTableName(queryId);
                    adfTable.setSql(sql);
                    adfTable.setView(true);
                    adfTable.setEntityName(entityName);
                    GlobalConfig.globalQueryList.add(adfTable);
                }

            }



        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }


    }
}